home *** CD-ROM | disk | FTP | other *** search
- ; -*-Lisp-*-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;
- ; File: ifthen.lsp
- ; RCS: $Header: $
- ; Description: If then rules - mini expert from Ch. 18 of Winston and Horn
- ; Written using recursion without progs. Added function 'how' to
- ; explain deductions.
- ; Use:
- ; After loading type (deduce). It will make all the deductions
- ; given the list fact. If you want to know how it deduced something
- ; type (how '(a deduction)) for example (how '(animal is tiger))
- ; and so on.
- ; Author: Winston and Horn and ???
- ; Created: Sat Oct 5 20:53:43 1991
- ; Modified: Sat Oct 5 20:55:13 1991 (Niels Mayer) mayer@hplnpm
- ; Language: Lisp
- ; Package: N/A
- ; Status: X11r5 contrib tape release
- ;
- ; WINTERP Copyright 1989, 1990, 1991 Hewlett-Packard Company (by Niels Mayer).
- ; XLISP version 2.1, Copyright (c) 1989, by David Betz.
- ;
- ; Permission to use, copy, modify, distribute, and sell this software and its
- ; documentation for any purpose is hereby granted without fee, provided that
- ; the above copyright notice appear in all copies and that both that
- ; copyright notice and this permission notice appear in supporting
- ; documentation, and that the name of Hewlett-Packard and Niels Mayer not be
- ; used in advertising or publicity pertaining to distribution of the software
- ; without specific, written prior permission. Hewlett-Packard and Niels Mayer
- ; makes no representations about the suitability of this software for any
- ; purpose. It is provided "as is" without express or implied warranty.
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ; rules data base
-
- (setq rules
- '((rule identify1
- (if (animal has hair))
- (then (animal is mammal)))
- (rule identify2
- (if (animal gives milk))
- (then (animal is mammal)))
- (rule identify3
- (if (animal has feathers))
- (then (animal is bird)))
- (rule identify4
- (if (animal flies)
- (animal lays eggs))
- (then (animal is bird)))
- (rule identify5
- (if (animal eats meat))
- (then (animal is carnivore)))
- (rule identify6
- (if (animal has pointed teeth)
- (animal has claws)
- (animal has forward eyes))
- (then (animal is carnivore)))
- (rule identify7
- (if (animal is mammal)
- (animal has hoofs))
- (then (animal is ungulate)))
- (rule identify8
- (if (animal is mammal)
- (animal chews cud))
- (then (animal is ungulate)
- (even toed)))
- (rule identify9
- (if (animal is mammal)
- (animal is carnivore)
- (animal has tawny color)
- (animal has dark spots))
- (then (animal is cheetah)))
- (rule identify10
- (if (animal is mammal)
- (animal is carnivore)
- (animal has tawny color)
- (animal has black stripes))
- (then (animal is tiger)))
- (rule identify11
- (if (animal is ungulate)
- (animal has long neck)
- (animal has long legs)
- (animal has dark spots))
- (then (animal is giraffe)))
- (rule identify12
- (if (animal is ungulate)
- (animal has black stripes))
- (then (animal is zebra)))
- (rule identify13
- (if (animal is bird)
- (animal does not fly)
- (animal has long neck)
- (animal has long legs)
- (animal is black and white))
- (then (animal is ostrich)))
- (rule identify14
- (if (animal is bird)
- (animal does not fly)
- (animal swims)
- (animal is black and white))
- (then (animal is penguin)))
- (rule identify15
- (if (animal is bird)
- (animal flys well))
- (then (animal is albatross)))))
- ; utility functions
- (defun squash(s)
- (cond ((null s) ())
- ((atom s) (list s))
- (t (append (squash (car s))
- (squash (cdr s))))))
-
- (defun p(s)
- (princ (squash s)))
-
- ; functions
-
- ; function to see if an item is a member of a list
-
- (defun member(item list)
- (cond((null list) ()) ; return nil on end of list
- ((equal item (car list)) list) ; found
- (t (member item (cdr list))))) ; otherwise try rest of list
-
- ; put a new fact into the facts data base if it is not already there
-
- (defun remember(newfact)
- (cond((member newfact facts) ()) ; if present do nothing
- (t ( setq facts (cons newfact facts)) newfact)))
-
- ; is a fact there in the facts data base
-
- (defun recall(afact)
- (cond ((member afact facts) afact) ; it is here
- (t ()))) ; no it is'nt
-
- ; given a rule check if all the if parts are confirmed by the facts data base
-
- (defun testif(iflist)
- (cond((null iflist) t) ; all satisfied
- ((recall (car iflist)) (testif (cdr iflist))) ; keep searching
- ; if one is ok
- (t ()))) ; not in facts DB
-
- ; add the then parts of the rules which can be added to the facts DB
- ; return the ones that are added
-
- (defun usethen(thenlist addlist)
- (cond ((null thenlist) addlist) ; all exhausted
- ((remember (car thenlist))
- (usethen (cdr thenlist) (cons (car thenlist) addlist)))
- (t (usethen (cdr thenlist) addlist))))
-
- ; try a rule
- ; return t only if all the if parts are satisfied by the facts data base
- ; and at lest one then ( conclusion ) is added to the facts data base
-
- (defun tryrule(rule &aux ifrules thenlist addlist)
- (setq ifrules (cdr(car(cdr(cdr rule)))))
- (setq thenlist (cdr(car(cdr(cdr(cdr rule))))))
- (setq addlist '())
- (cond (( testif ifrules)
- (cond ((setq addlist (usethen thenlist addlist))
- (p (list "Rule " (car(cdr rule)) "\n\tDeduced " addlist "\n\n"))
- (setq ruleused (cons rule ruleused))
- t)
- (t ())))
- (t ())))
-
- ; step through one iteration if the forward search
- ; looking for rules that can be deduced from the present fact data base
-
- (defun stepforward( rulelist)
- (cond((null rulelist) ()) ; all done
- ((tryrule (car rulelist)) t)
- ( t (stepforward(cdr rulelist)))))
-
- ; stepforward until you cannot go any further
-
- (defun deduce()
- (cond((stepforward rules) (deduce))
- (t t)))
-
- ; function to answer if a fact was used to come to a certain conclusion
- ; uses the ruleused list cons'ed by tryrule to answer
-
- (defun usedp(rule)
- (cond ((member rule ruleused) t) ; it has been used
- (t () ))) ; no it hasnt
-
- ; function to answer how a fact was deduced
-
- (defun how(fact)
- (how2 fact ruleused nil))
-
- (defun how2(fact rulist found)
- (cond ((null rulist) ; if the rule list exhausted
- (cond (found t) ; already answered the question return t
- ((recall fact) (p (list fact " was a given fact\n")) t) ;known fact
- (t (p (list fact " -- not a fact!\n")) ())))
-
- ((member fact (thenpart (car rulist))) ; if rulist not empty
- (setq found t) ; and fact belongs to the then part of a rule
- (p (list fact " was deduced because the following were true\n"))
- (printifs (car rulist))
- (how2 fact (cdr rulist) found))
- (t (how2 fact (cdr rulist) found))))
-
- ; function to return the then part of a rule
-
- (defun thenpart(rule)
- (cdr(car(cdr(cdr(cdr rule))))))
-
- ; function to print the if part of a given rule
-
- (defun printifs(rule)
- (pifs (cdr(car(cdr(cdr rule))))))
-
- (defun pifs(l)
- (cond ((null l) ())
- (t (p (list "\t" (car l) "\n"))
- (pifs (cdr l)))))
-
-
- ; initial facts data base
- ; Uncomment one or make up your own
- ; Then run 'deduce' to find deductions
- ; Run 'how' to find out how it came to a certain deduction
-
- ;(setq facts
- ; '((animal has dark spots)
- ; (animal has tawny color)
- ; (animal eats meat)
- ; (animal has hair)))
-
- (setq facts
- '((animal has hair)
- (animal has pointed teeth)
- (animal has black stripes)
- (animal has claws)
- (animal has forward eyes)
- (animal has tawny color)))
-
-
- (setq rl1
- '(rule identify14
- (if (animal is bird)
- (animal does not fly)
- (animal swims)
- (animal is black and white))
- (then (animal is penguin))))
-
- (setq rl2
- '(rule identify10
- (if (animal is mammal)
- (animal is carnivore)
- (animal has tawny color)
- (animal has black stripes))
- (then (animal is tiger))))
-
- ; Initialization
- (expand 10)
- (setq ruleused nil)
-